package tt.dz.egobus.servicemanager.facade.interator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import tt.dz.egobus.base.context.SpringApplicationHolder;
import tt.dz.egobus.servicemanager.core.exception.BusinessException;
import tt.dz.egobus.servicemanager.core.interceptor.LoggerInterceptorHandler;

import java.lang.reflect.Method;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Anson
 * @date 17-3-21
 * @name 采用adapter方式集成dubbo日志输出
 * @since 1.0.1
 */
public class LoggerInterceptor implements Interceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggerInterceptor.class);
    private static final String EXECUTOR_NAME = "standardThreadExecutor";

    private final LoggerInterceptorHandler handler;


    private final AtomicReference<ThreadPoolExecutor> threadPoolExecutorAtomicReference = new AtomicReference<>();

    private final ReentrantLock lock = new ReentrantLock();

    public LoggerInterceptor() {
        handler = new LoggerInterceptorHandler();

    }

    private ThreadPoolExecutor handlerExecutor() {
        ThreadPoolExecutor executor = this.threadPoolExecutorAtomicReference.get();
        if (executor == null) {
            try {
                lock.lock();
                if ((executor = this.threadPoolExecutorAtomicReference.get()) == null) {
                    ApplicationContext applicationContext = SpringApplicationHolder.getApplicationContext();
                    if (applicationContext != null) {
                        boolean isContainerExecutor = applicationContext.containsBean(EXECUTOR_NAME);
                        if (isContainerExecutor) {
                            executor = applicationContext.getBean(EXECUTOR_NAME, ThreadPoolExecutor.class);
                            if (executor != null) {
                                this.threadPoolExecutorAtomicReference.set(executor);
                            }
                        }
                    }
                }
            } finally {
                lock.unlock();
            }
        }
        return executor;
    }

    @Override
    public boolean interceptBefore(Object obj, Method method, Object[] args) throws BusinessException {
        ThreadPoolExecutor executor = this.handlerExecutor();
        boolean isAccexcpt = false;
        if ((isAccexcpt = executor != null)) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        handler.interceptBefore(obj, method, args);
                    } catch (Exception e) {
                        LOGGER.error("当前reference异常", e);
                    }
                }
            });
        }

        return isAccexcpt;
    }

    @Override
    public Object interceptPost(Object obj, Method method, Object[] args, Object result) throws BusinessException {
        ThreadPoolExecutor executor = this.handlerExecutor();
        boolean isAccexcpt = false;
        if ((isAccexcpt = executor != null)) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        handler.interceptPost(obj, method, args, result);
                    } catch (Exception e) {
                        LOGGER.error("当前reference异常", e);
                    }
                }
            });
        }
        return isAccexcpt;
    }
}
